import datetime
import logging
from dataclasses import dataclass

from src.application.order.converters import convert_order_entity_to_dto
from src.application.order.dto.order import OrderDTO
from src.application.order.enums import OrderPeriod, OrderType
from src.application.order.uow import OrderUoW
from src.application.proxy.converters import convert_proxy_dto_to_entity
from src.application.proxy.dto.proxy import ProxyDTO
from src.domain.order.aggregates.order import OrderAggregate
from src.domain.user.value_objects import TelegramUserId

logger = logging.getLogger(__name__)


@dataclass(frozen=True)
class CreateOrder:
    buyer_tg_id: int
    order_type: OrderType
    order_summ: float
    category_id: int
    period: OrderPeriod
    proxies: list[ProxyDTO]
    country_id: int
    provider_id: int
    site_id: int | None
    vpn_server_id: int | None
    expiring_on: datetime.datetime


class CreateOrderHandler:
    """Создание заказа"""

    def __init__(
        self,
        *,
        uow: OrderUoW,
    ) -> None:
        self._uow = uow

    async def __call__(self, command: CreateOrder) -> OrderDTO:
        user_tg_id = TelegramUserId(value=command.buyer_tg_id)
        user = await self._uow.user_repo.acquire_user_by_id(user_tg_id)
        proxy_entities = [convert_proxy_dto_to_entity(proxy) for proxy in command.proxies]

        order = OrderAggregate.create_order(
            buyer_id=user.id,
            order_summ=command.order_summ,
            order_summ_total=command.order_summ,
            order_type=command.order_type,
            category_id=command.category_id,
            period=command.period,
            proxies=proxy_entities,
            country_id=command.country_id,
            provider_id=command.provider_id,
            site_id=command.site_id,
            vpn_server_id=command.vpn_server_id,
            expiring_on=command.expiring_on,
        )

        user.add_proxies(proxy_entities)
        user.decrease_balance(order.summ)  # TODO Сделать обработку ошибки
        # TODO Обновлять статус у всех прокси на ProxyStatus.sold

        try:
            await self._uow.order_repo.create_order(order)
            await self._uow.user_repo.update_user(user)
        except Exception as err:
            await self._uow.rollback()
            raise err

        await self._uow.commit()

        logger.info("Order created", extra={"order": order})

        order_dto = convert_order_entity_to_dto(order)

        return order_dto
